/**
 * Carousel
 *
 * @author		Allen Chou
 * @version		1.0.1 (last update: Aug 11 2008)
 * @link        http://cjcat.blogspot.com
 * @link		http://cjcat2266.deviantart.com
 */

package idv.cjcat.display.carousel {
	import flash.display.*;
	import flash.errors.IllegalOperationError;
	import flash.events.*;
	
	import idv.cjcat.display.NonAddChildContainer;

	public class Carousel extends NonAddChildContainer {
		
		public var phase:Number = 0;
		
		public var autoAlpha:Boolean;
		
		public var phaseOffsetX:Number = 0;
		public var phaseOffsetY:Number = 0;
		public var phaseOffsetZ:Number = 0;
		public var phaseOffsetS:Number = 0; //scale
		public var phaseOffsetA:Number = 0; //alpha
		public var phaseOffsetR:Number = 0;
		
		public var centerX:Number = 0;
		public var centerY:Number = 0;
		public var centerS:Number = 1;	//scale
		public var centerA:Number = 1;	//alpha
		public var centerR:Number = 0;	//rotation
		
		public var radiusX:Number = 200;
		public var radiusY:Number = 0;
		public var radiusS:Number = 0;	//scale
		public var radiusA:Number = 0;	//alpha
		public var radiusR:Number = 0;	//rotation
		
		public var frequencyX:int = 1;
		public var frequencyY:int = 1;
		public var frequencyZ:int = 1;
		
		public var absoluteR:Boolean = false;
		
		private var _axis:DisplayObject = null;
		private var _ponies:Array = new Array();
		
		public function Carousel(_ponies:Array = null, autoAlpha:Boolean = true) {
			if (_ponies != null) {
				for (var i:int = 0; i < _ponies.length; i++) add(_ponies[i]);
			}
			this.autoAlpha = autoAlpha;
		}
		
		private var tempP:Pony;
		public function render():void {
			if (_axis != null) {
				if (_sprite.contains(_axis)) _sprite.removeChild(_axis);
			}
			
			var obj:DisplayObject;
			var i:int;
			var j:Number;
			for (i = 0; i < _ponies.length; i++) {
				
				//processing position
				obj = _ponies[i].obj;
				obj.x = centerX + radiusX * Math.sin((_ponies[i].phase + phase) * frequencyX + phaseOffsetX);
				obj.y = centerY + radiusY * Math.cos((_ponies[i].phase + phase) * frequencyY + phaseOffsetY);
				
				//determining depth
				j = (_ponies[i].phase + phase) * frequencyZ + phaseOffsetZ;
				_ponies[i]._depth = Math.cos(j);
				
				//processing scale
				obj.scaleX = obj.scaleY = centerS + radiusS * Math.cos(j + phaseOffsetS);
				
				//processing alpha
				obj.alpha = centerA + radiusA * Math.cos(j + phaseOffsetA);
				if (obj.alpha <= 0 && autoAlpha) {
					obj.visible = false;
				} else {
					obj.visible = true;
				}
				
				//processing rotation
				obj.rotation = centerR + radiusR * Math.sin(j + phaseOffsetR);
				
			}
			
			if (_axis != null) {
				tempP = new Pony(_axis, 0);
				tempP._depth = 0;
				_ponies.push(tempP);
			}
			
			_ponies.sort(sortDepth);
			
			for (i = 0; i < _ponies.length; i++) {
				_sprite.addChild(_ponies[i]._obj);
			}
			
			if (_axis != null) _ponies.splice(_ponies.indexOf(tempP), 1);
		}
		
		private function sortDepth(a:Pony, b:Pony):Number {
			if (a._depth < b._depth) {
				return -1;
			} else {
				return 1;
			}
			return 0;
		}
		
		public function add(pony:Pony):Pony {
			for (var i:int = 0; i < _ponies.lengt; i++) {
				if (_ponies[i] === pony) return pony;
			}
			if (pony._carousel != null && pony._carousel != this) throw new IllegalOperationError("This Pony already belongs to another Carousel.");
			pony._carousel = this;
			_ponies.push(pony);
			_sprite.addChild(pony._obj);
			return pony;
		}
		
		public function remove(pony:Pony):Pony {
			var pony:Pony;
			var found:Boolean = false;
			for (var i:int = 0; i < _ponies.length; i++) {
				if (_ponies[i] === pony) {
					pony._carousel = null;
					_sprite.removeChild(_ponies[i]._obj);
					return Pony(_ponies.splice(i, 1)[0]);
				}
			}
			return null;
		}
		
		public function clear():void {
			for (var i:int = 0; i < _ponies.length; i++) remove(_ponies[i]);
		}
		
		public function get axis():DisplayObject { return _axis; }
		public function set axis(value:DisplayObject):void {
			if (value == null) {
				_sprite.removeChild(value);
			} else {
				_axis = value;
				_axis.x = centerX;
				_axis.y = centerY;
			}
		}
		
	}
}